package ivf

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	// cuckoo "github.com/seiflotfy/cuckoofilter"
)

func IntToBytes(n int) []byte {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, int64(n))
	if err != nil {
		fmt.Println("Int to []byte conversion error:", err)
		return nil
	}
	return buf.Bytes()
}

func PostingToBytes(p Posting) []byte {
	docIDBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(docIDBytes, uint64(p.DocID))

	// 将 TF float64 转换为字节（float64 是 64 位）
	tfBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(tfBytes, math.Float64bits(p.TF))

	// 连接所有字节
	data := append(docIDBytes, tfBytes...)
	data = append(data, p.PrevHash...)
	return data
}

// BytesToPosting 函数接受一个字节切片并尝试将其解析回 Posting 结构体
func BytesToPosting(data []byte) (*Posting, error) {
	if len(data) < 16 { // 确保数据长度足够，避免出现切片越界错误
		return nil, fmt.Errorf("data is too short to be a valid Posting")
	}

	// 读取 DocID，它占据前 8 个字节
	docID := int(binary.BigEndian.Uint64(data[:8]))

	// 读取 TF，它紧接着 DocID 占据接下来的 8 个字节
	tfBits := binary.BigEndian.Uint64(data[8:16])
	tf := math.Float64frombits(tfBits)

	// 剩余的字节都属于 PrevHash
	prevHash := data[16:]

	return &Posting{
		DocID:    docID,
		TF:       tf,
		PrevHash: prevHash,
	}, nil
}

// Document 表示一个简单的文档，这里只包含文档ID和文本内容
type BOW struct {
	ID     int
	Vector []float32
}

// Posting 表示倒排列表中的一条记录，包含文档ID和该词在文档中的频率
type Posting struct {
	DocID    int
	TF       float64 // tfidf
	PrevHash []byte  //前向哈希保持连续
}

var codebook map[int]int

// calculateIDFAndSortPostings 计算 IDF 并更新 Posting 的 TF-IDF 值，然后对 Posting 进行排序
func (index *InvertedIndex) CalculateIDFAndSortPostings() {
	docCount := float64(len(index.Docs))
	for term, postings := range index.Index {
		index.Weight[term] = len(postings)
		idf := math.Log(docCount / (float64(len(postings)) + 0))
		// fmt.Println(term, docCount, len(postings), idf)
		for i, posting := range postings {
			// 更新 TF 值为 TF-IDF 值
			index.Index[term][i].TF = posting.TF * idf
		}
		// 根据 TF-IDF 值对 postings 排序，这里使用简单的冒泡排序，实际应用中可能需要更高效的排序算法
		for i := 0; i < len(postings)-1; i++ {
			for j := 0; j < len(postings)-i-1; j++ {
				if postings[j].TF < postings[j+1].TF {
					postings[j], postings[j+1] = postings[j+1], postings[j]
				}
			}
		}
		//排序后计算prevhash
		for i := len(postings) - 2; i >= 0; i-- {
			postings[i].PrevHash = GetPrevHash(postings[i+1])
		}
		//计算digest
		index.Digest[term] = GetDigest(len(postings), index.Filter[term], GetPrevHash(postings[0]))
	}
}

// 在列表中查找doc_id为id的位置
func FindLoca(id int, posting []Posting) int {
	for i, p := range posting {
		// fmt.Println(i, p)
		if p.DocID == id {
			return i
		}
	}
	return -1
}

// 将文档转化为向量
// func ToVector(doc Document) map[string]int {
// 	words := strings.Fields(doc.Text)
// 	wordFreq := make(map[string]int)
// 	for _, word := range words {
// 		wordFreq[word]++
// 	}
// 	return wordFreq
// }
